package com.mida.app.report.process.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.mida.app.report.config.CriticalValueForwardConfiguration;
import com.mida.app.report.enumData.*;
import com.mida.app.report.process.DocReportListProcess;
import com.mida.app.report.process.DocReportProcess;
import com.mida.app.report.service.DetailCodingSystemService;
import com.mida.app.report.service.DocReportServiceLockService;
import com.mida.app.report.service.RequestFormService;
import com.mida.app.report.utils.ReportUtil;
import com.mida.app.report.vo.request.PatientPageInfoVo;
import com.mida.app.report.vo.request.ReqeustServiceInstanceVo;
import com.mida.app.report.vo.request.RequestAndPatientInfoVo;
import com.mida.app.report.vo.request.RequestPsersonsoidRequest;
import com.mida.bms.customer.api.PersonOperationApi;
import com.mida.bms.report.api.DocReportApi;
import com.mida.bms.report.api.DocReportPdfApi;
import com.mida.bms.report.entity.DocReportServiceLock;
import com.mida.bms.report.vo.*;
import com.mida.bms.requestform.api.RequestFormApi;
import com.mida.bms.requestform.enums.RequestOperateEnum;
import com.mida.bms.requestform.response.DataCenterPatientMedicalInfoVo;
import com.mida.bms.requestform.response.QueryPatientMedicalReportVo;
import com.mida.bms.requestform.vo.requestform.ApntRequestLifeCycleVo;
import com.mida.dms.mdm.api.provider.ICodingRuleInfoApi;
import com.mida.dms.mdm.api.provider.IOrgInfoApi;
import com.mida.dms.mdm.api.provider.IParameterApi;
import com.mida.dms.mdm.dto.ParameterDto;
import com.mida.dms.mdm.dto.UserDto;
import com.mida.dms.mdm.pojo.auto.MsdParameterValue;
import com.mida.dms.mdm.vo.provider.BaseOrgInfoVo;
import com.mida.tool.common.result.ActionResult;
import com.mida.tool.common.result.ListResult;
import com.mida.tool.common.ret.RespBody;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <h1>报告书写</h1>
 * <p>
 *
 * </p>
 *
 * @author jian.li on 2021/4/28 9:30
 */
@Service
@Slf4j
public class DocReportProcessImpl extends BaseProcess implements DocReportProcess {

    public static final long RESOURCE_INFO_SOID = 18413530021628928L;//应用资源--写报告soid
    public static final long CODING_RULE_INFO_SOID = 27797392413690880L;//报告编码soid


    @Autowired
    private DocReportListProcess docReportListProcess;

    // 申请单
    @Autowired
    private RequestFormApi requestFormApi;    // 申请单

    @Autowired
    private PersonOperationApi personOperationApi;
    @Autowired
    private ICodingRuleInfoApi iCodingRuleInfoApi;

    @Autowired
    private IOrgInfoApi iOrgInfoApi;

    @Autowired
    private IParameterApi iParameterApi;

    @Autowired
    private DocReportApi docReportApi;

    @Autowired
    private DocReportPdfApi docReportPdfApi;

    @Autowired
    private RequestFormService requestFormService;

    @Autowired
    private DetailCodingSystemService detailCodingSystemService;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    CriticalValueForwardConfiguration criticalValueForwardConfiguration;

    @Autowired
    private DocReportServiceLockService docReportServiceLockService;
    @Value("${critical.url}")
    private String criticalUrl;

    // 假数据
    @Value("${action.doc}")
    private boolean switchSign;

    @Value("file:config/patientinfo.txt")
    private File filePatientinfo;

    @Value("file:config/patientinfoByExam.txt")
    private File filePatientinfoByExam;

    @Value("file:config/patientinfoByRegistion.txt")
    private File filePatientinfoByRegistion;

    // 登记号，检查号假数据
    @Value("${action.doc.test}")
    private boolean testDate;

    /**
     * 初始化报告模板
     *
     * @param docReportInitializationRequest 初始化报告模板请求参数
     * @return
     */
    @Override
    public ListResult<ReportInitializationResult> initializeDocReport(DocReportInitializationRequest docReportInitializationRequest, HttpServletRequest httpServletRequest) {
        //TODO
        // 获取用户信息
        String reportDoctor = null;
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto user = userDtoresult.getData();
        if (ObjectUtils.isNotEmpty(user)) {
            reportDoctor = user.getNickname();
        }

        // mock数据
        if (!switchSign) {
            ListResult result = new ListResult();
            ReportInitializationResult reportInitializationResult = new ReportInitializationResult();
            List<PatientInfoVo> listTmp = new ArrayList<PatientInfoVo>();
            Map<String, String> info = new HashMap<>();
            if (ObjectUtils.isEmpty(docReportInitializationRequest.getRequestSoid())) {
                log.error("申请单标识不能为空");
                buildBadRequestListWarn(result, "申请单标识不能为空");
                return result;
            }

            Long requestSoid = docReportInitializationRequest.getRequestSoid();
            if (filePatientinfo.exists()) {
                listTmp = ReportUtil.gainMockPatientInfo(listTmp, filePatientinfo);
            }

            if (CollectionUtils.isNotEmpty(listTmp)) {
                // 打包初始化报告所需的数据(一般信息,检查信息)返给前端
                for (int i = 0; i < listTmp.size(); i++) {
                    //直译病人信息
                    com.mida.bms.report.vo.PatientInfoVo patientInfoVo = listTmp.get(i);
                    if (patientInfoVo.getRequestNo().longValue() == requestSoid.longValue()) {
                        ReportUtil.packInitializedReportInfoMock(reportDoctor, info, patientInfoVo);
                    }
                    info.put(ReportFragmentSlotInfo.WRITE_DOC.code.toString(), user.getNickname());
                }
            }
            reportInitializationResult.setRequisitionInfo(info);
            buildListSuccess(result, reportInitializationResult);
            return result;
        } else {// 真实业务操作
            log.info("开始初始化模板报告,初始化条件: " + "申请单标识: " + docReportInitializationRequest.getRequestSoid());
            StopWatch stopWatch = StopWatch.createStarted();
            ListResult result = new ListResult();
            ReportInitializationResult reportInitializationResult = new ReportInitializationResult();
            Map<String, String> info = new HashMap<>();

            if (ObjectUtils.isEmpty(docReportInitializationRequest.getRequestSoid())) {
                log.error("申请单标识不能为空");
                buildBadRequestListWarn(result, "申请单标识不能为空");
                return result;
            }

            try {
                // 从上游获取初始化所需信息(一般信息,检查信息)
                List<RequestPsersonsoidRequest> requestList = new ArrayList<>();
                RequestPsersonsoidRequest requestPsersonsoidRequest = new RequestPsersonsoidRequest();
                requestPsersonsoidRequest.setRequestSoid(docReportInitializationRequest.getRequestSoid().toString());
                requestPsersonsoidRequest.setPersonSoid(docReportInitializationRequest.getPersonSoid());
                requestList.add(requestPsersonsoidRequest);
                List<RequestAndPatientInfoVo> patientMedicalByRequestSoids = requestFormService.findPatientMedicalByRequestSoids(requestList);
                if (ObjectUtils.isNotEmpty(patientMedicalByRequestSoids)) {
                    for (RequestAndPatientInfoVo patientMedicalByRequestSoid : patientMedicalByRequestSoids) {
                        // 打包初始化报告信息
                        packInitializedReportInfo(user, result, reportInitializationResult, info, patientMedicalByRequestSoid);
                    }
                }

            } catch (Exception e) {
                log.error("初始化模板报告发送异常", e);
                buildListWarn(result, "初始化模板报告失败");
            } finally {
                stopWatch.stop();
                log.info("本次初始化模板报告耗时: " + stopWatch.getTime() + "ms");
            }
            return result;
        }
    }

    /**
     * 暂存报告
     *
     * @param request 暂存报告请求参数
     * @return
     */
    @Override
    public ListResult<ReportResult> saveTemporarily(DocReportPreservationRequest request, HttpServletRequest httpServletRequest) throws NoSuchFieldException {

        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();

        Long employeeSoid = null;
        // 提交科室标识
        String submitDeptSoid = null;

        UserDto loginUser = userDtoresult.getData();
        if (ObjectUtils.isEmpty(loginUser)) {
            ListResult result = new ListResult();
            buildListWarn(result, "获取不到用户信息");
            return result;
        }

        employeeSoid = loginUser.getEmployeeSoid();
        List<String> businessUnitSoids = loginUser.getBusinessUnitSoids();
        if (CollectionUtils.isNotEmpty(businessUnitSoids)) {
            submitDeptSoid = businessUnitSoids.get(0);
        }

        // 角色标识
        String customerSoid = null;
        // 患者信息标识(From our system)
        String apntPersonSoid = null;
        // 病人标识(From HIS)
        String patientId = null;
        //病人姓名
        String personName = null;

        List<RequestPsersonsoidRequest> requestList = new ArrayList<>();
        RequestPsersonsoidRequest requestPsersonsoidRequest = new RequestPsersonsoidRequest();
        requestPsersonsoidRequest.setRequestSoid(request.getRequestSoid().toString());
        requestPsersonsoidRequest.setPersonSoid(request.getPersonSoid());
        requestList.add(requestPsersonsoidRequest);

        Map<String, String> patientInfoMap = new HashMap<>();
        if (!switchSign) {
            // 切换mock数据,从mock文件中获取患者信息
            gainRoleAndPatientInfoMock(request, submitDeptSoid, customerSoid, apntPersonSoid, patientId, patientInfoMap);
        } else {
            // 获取角色标识,患者姓名,病人号,提交科室soid,患者信息标识
            personName = gainRoleAndPatientInfo(request, submitDeptSoid, customerSoid, patientId, personName, requestList, requestPsersonsoidRequest, patientInfoMap);

            // 校验上游患者姓名是否修改
            if (StringUtils.isNotEmpty(personName)) {
                ReportUtil.checkPersonName(request, personName);
            }
        }

        request.setEmployeeSoid(employeeSoid);
        // 报告自身状态置为草稿
        request.setReportStatus(ReportStatus.DRAFT.code);
        // 报告流转状态置为待书写
        request.setReportProcessStatus(ReportProcessStatus.TO_BE_WRITTEN.code);

        // 调用中台暂存服务
        ListResult<ReportResult> reportResultListResult = docReportApi.saveTemporarily(request);
        return reportResultListResult;
    }

    /**
     * 签署报告
     *
     * @param request 签署报告请求参数
     * @return
     */
    @Override
    public ListResult<String> saveDocReport(DocReportPreservationRequest request, HttpServletRequest httpServletRequest) throws NoSuchFieldException {
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        Long employeeSoid = null;
        ListResult listResult = null;
        UserDto loginUser = userDtoresult.getData();
        try {
            if (ObjectUtils.isEmpty(loginUser)) {
                ListResult result = new ListResult();
                buildListWarn(result, "获取不到用户信息");
                return result;
            }
            employeeSoid = loginUser.getEmployeeSoid();

            // 角色标识
            String customerSoid = null;
            // 患者信息标识(From our system)
            String apntPersonSoid = null;
            // 病人标识(From HIS)
            // String patientSoid = null;
            String patientId = null;
            //病人姓名
            String personName = null;

            List<RequestPsersonsoidRequest> requestList = new ArrayList<>();
            RequestPsersonsoidRequest requestPsersonsoidRequest = new RequestPsersonsoidRequest();
            requestPsersonsoidRequest.setRequestSoid(request.getRequestSoid().toString());
            requestPsersonsoidRequest.setPersonSoid(request.getPersonSoid());
            requestList.add(requestPsersonsoidRequest);

            Map<String, String> patientInfoMap = new HashMap<>();
            if (!switchSign) {
                // 获取mock数据(患者信息标识)
                gainRoleAndPatientInfoMock(request, null, customerSoid, apntPersonSoid, patientId, patientInfoMap);
            } else {
                // 获取角色标识,患者姓名,病人号,提交科室soid,患者信息标识
                personName = gainRoleAndPatientInfo(request, null, customerSoid, patientId, personName, requestList, requestPsersonsoidRequest, patientInfoMap);

                // 校验上游患者姓名是否修改
                if (StringUtils.isNotEmpty(personName)) {
                    ReportUtil.checkPersonName(request, personName);
                }
            }

            //获取报告流水号
            String reportVisitSoid = gainReportVisitSoid(loginUser);
            request.setReportVisitSoid(reportVisitSoid);
            request.setEmployeeSoid(employeeSoid);
            // 报告自身状态为书写完成
            request.setReportStatus(ReportStatus.WRITE_COMPLETED.code);
            // 报告流转状态为初写完成待审核
            request.setReportProcessStatus(ReportProcessStatus.TO_BE_REVIEWED.code);

            // 调用中台签署报告服务
            listResult = docReportApi.saveDocReport(request);
            if (listResult.getStatus() != HttpStatus.OK.value()) {
                return listResult;
            }

            // 修改申请单状态
            modifyRequestFormStatus(request.getMsdServiceInstanceSoidList(), employeeSoid, request.getRequestSoid());
        } finally {
            // TODO 需要解锁报告
            //删除锁
            deleteLock(request, loginUser);
        }
        return listResult;
    }

    /**
     * 报告回显
     *
     * @param request 报告回显请求参数
     * @return
     */
    @Override
    public ListResult<ReportResult> getDocReport(DocReportInitializationRequest request, HttpServletRequest httpServletRequest) {

        // 报告加急状态
        String emergencySign = null;

        // 获取上游申请单信息
        emergencySign = gainEmergencySign(request, emergencySign);
        request.setEmergencySign(emergencySign);

        return docReportApi.getDocReport(request);
    }

    /**
     * 报告(初写完成待审核)编辑/撤回
     *
     * @param stReportSoid 报告存储信息标识
     * @return
     */
    @Override
    public ActionResult editDocReport(Long stReportSoid, HttpServletRequest httpServletRequest) {

        Long employeeSoid = null;
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto loginUser = userDtoresult.getData();
        if (ObjectUtils.isEmpty(loginUser)) {
            ActionResult result = new ActionResult();
            buildActionWarn(result, "获取不到用户信息");
            return result;
        }
        employeeSoid = loginUser.getEmployeeSoid();


        return docReportApi.editDocReport(stReportSoid, employeeSoid);
    }

    /**
     * 业务态保存报告模板
     *
     * @param request 业务态保存报告模板请求参数
     * @return
     */
    @Override
    public ActionResult saveTemplate(DocReportPreservationRequest request, HttpServletRequest httpServletRequest) {
        return docReportApi.saveTemplate(request);
    }

    /**
     * 接收报告，将报告改为已审核，保存报告
     *
     * @param reportRequest
     * @return
     */
    @Override
    @Transactional
    public ActionResult modifyReportStatus(DocReportPreservationRequest reportRequest, HttpServletRequest httpServletRequest) {
        ActionResult result = new ActionResult();
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto loginUser = userDtoresult.getData();
        try {
            Long employeeSoid = null;
            if (ObjectUtils.isEmpty(loginUser)) {
                buildActionWarn(result, "获取不到用户信息");
                return result;
            }
            employeeSoid = loginUser.getEmployeeSoid();


            reportRequest.setEmployeeSoid(employeeSoid);
            // CT报告默认打分结果(图片质量:甲,报告质量:高,阴阳性:阴)
            if (reportRequest.getPictureQuality() == null) {
                reportRequest.setPictureQuality(PictureQuality.RANK_ONE.code);
            }
            if (reportRequest.getReportLevel() == null) {
                reportRequest.setReportLevel(ReportQuality.ADVANCED.code);
            }
            if (reportRequest.getNegativePositive() == null) {
                reportRequest.setNegativePositive(YinAndYang.YIN.code);
            }
            ActionResult actionResult = docReportApi.modifyReportStatus(reportRequest);
            if (200 != actionResult.getStatus()) {
                return actionResult;
            }

            Long stReportSoid = reportRequest.getStReportSoid();
            //报告和检查实例的关系
            List<DocReportRequisitionRelationVo> docReportRequisitionRelationVos = docReportApi.selectByStReportSoid(stReportSoid);
            if (CollectionUtils.isEmpty(docReportRequisitionRelationVos)) {
                buildActionWarn(result, "没有查到报告和检查实例的关系");
                return result;
            }
            // 修改申请单状态
            modifyRequestFormStatus(employeeSoid, docReportRequisitionRelationVos);
            buildActionSuccess(result);
        } finally {
            // TODO 需要解锁报告
            //删除锁
            deleteLock(reportRequest, loginUser);
        }
        return result;
    }

    /**
     * 退回报告，将报告改为审核已退回
     *
     * @param
     * @return
     */
    @Override
    public ActionResult modifyStatus(String stReportSoid, HttpServletRequest httpServletRequest) {
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        Long employeeSoid = null;
        ActionResult result = new ActionResult();
        UserDto loginUser = userDtoresult.getData();
        if (ObjectUtils.isEmpty(loginUser)) {
            buildActionWarn(result, "获取不到用户信息");
            return result;
        }
        employeeSoid = loginUser.getEmployeeSoid();

        //报告和检查实例的关系
        List<DocReportRequisitionRelationVo> docReportRequisitionRelationVos = docReportApi.selectByStReportSoid(Long.valueOf(stReportSoid));
        if (CollectionUtils.isEmpty(docReportRequisitionRelationVos)) {
            buildActionWarn(result, "没有查到报告和检查实例的关系");
            return result;
        }

        // 修改申请单状态
        modifyRequestFormStatus(employeeSoid, docReportRequisitionRelationVos);
        return docReportApi.modifyStatus(stReportSoid, employeeSoid);
    }

    /**
     * 报告通过审核，撤回报告
     *
     * @param
     * @return
     */
    @Override
    public ActionResult withdrawStatus(String stReportSoid) {
        ActionResult result = new ActionResult();
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        Long employeeSoid = null;
        UserDto loginUser = userDtoresult.getData();
        if (ObjectUtils.isEmpty(loginUser)) {
            buildActionWarn(result, "获取不到用户信息");
            return result;
        }
        employeeSoid = loginUser.getEmployeeSoid();

        // 调用中台审核撤回报告
        ActionResult actionResult = docReportApi.withdrawStatus(stReportSoid, employeeSoid);
        if (200 != actionResult.getStatus()) {
            return actionResult;
        }
        List<DocReportRequisitionRelationVo> docReportRequisitionRelationVos = docReportApi.selectByStReportSoid(Long.valueOf(stReportSoid));

        // 修改申请单状态
        modifyRequestFormStatus(employeeSoid, docReportRequisitionRelationVos);
        buildActionSuccess(result);
        return result;

    }

    /**
     * 保存报告pdf文件
     *
     * @param stReportSoid 报告存储信息标识
     * @param file
     * @return
     */
    @Override
    public ActionResult savePdf(Long stReportSoid, MultipartFile file, HttpServletRequest httpServletRequest) {

        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        Long employeeSoid = null;
        UserDto loginUser = userDtoresult.getData();
        if (ObjectUtils.isEmpty(loginUser)) {
            ActionResult result = new ActionResult();
            buildActionWarn(result, "获取不到用户信息");
            return result;
        }
        employeeSoid = loginUser.getEmployeeSoid();

        return docReportPdfApi.savePdf(stReportSoid, file, employeeSoid);
    }

    /**
     * 保存结构化报告
     *
     * @param request
     * @return
     */
    @Override
    public ActionResult saveStructuredReport(StructuredReportRequest request, HttpServletRequest httpServletRequest) {
        return docReportApi.saveStructuredReport(request);
    }

    /**
     * 根据登记号，检查号签署报告
     *
     * @param request
     * @return
     */
    @Override
    public ListResult<String> saveDocReportByRegistrationAndExam(DocReportPreservationRequest request, HttpServletRequest httpServletRequest) throws NoSuchFieldException {
        ListResult result = new ListResult();
        Long employeeSoid = null;
        // 提交科室soid
        String submitDeptSoid = null;
        ListResult listResult;
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto loginUser = userDtoresult.getData();
        try {

        if (ObjectUtils.isEmpty(loginUser)) {
            buildListWarn(result, "获取不到用户信息");
            return result;
        }
        employeeSoid = loginUser.getEmployeeSoid();
        List<String> businessUnitSoids = loginUser.getBusinessUnitSoids();
        if (CollectionUtils.isNotEmpty(businessUnitSoids)) {
            submitDeptSoid = businessUnitSoids.get(0);
        }

        // 角色标识
        String customerSoid = null;
        // 患者信息标识(From our system)
        String apntPersonSoid = null;
        // 病人标识(From HIS)
        String patientId = null;
        //报告类型
        Long reportType = request.getReportType();
        //检查标识
        Long operatorSoid = null;
        //登记号
        String registrationNo = null;
        //病人姓名
        String personName = null;

        List<RequestPsersonsoidRequest> requestList = new ArrayList<>();
        RequestPsersonsoidRequest requestPsersonsoidRequest = new RequestPsersonsoidRequest();
        requestPsersonsoidRequest.setRequestSoid(request.getRequestSoid().toString());
        requestPsersonsoidRequest.setPersonSoid(request.getPersonSoid());
        requestList.add(requestPsersonsoidRequest);


        if (ReportType.WRITE_REPORT_REQUEST.code.equals(reportType)) {
            // 按申请单方式书写报告
            return this.saveDocReport(request, httpServletRequest);
            // 按登记号/检查号书写报告
        }

        Map<String, String> patientInfoMap = null;
        if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType)
                || ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
            patientInfoMap = new HashMap<>();
            if (!testDate) {
                // 获取角色标识,患者相关信息mock数据
                gainRoleAndPatientInfoMergeMock(request, employeeSoid, customerSoid, apntPersonSoid, patientId, reportType, operatorSoid, registrationNo, patientInfoMap);
            } else {
                // 获取角色标识,患者相关信息
                personName = gainRoleAndPatientInfo(request, submitDeptSoid, customerSoid, patientId, personName, requestList, requestPsersonsoidRequest, patientInfoMap);
                // 校验上游患者姓名是否修改
                if (StringUtils.isNotEmpty(personName)) {
                    ReportUtil.checkPersonName(request, personName);
                }
            }
        }

        String reportVisitSoid = gainReportVisitSoid(userDtoresult.getData());
        request.setReportVisitSoid(reportVisitSoid);
        request.setEmployeeSoid(employeeSoid);
        // 报告流转状态为初写完成待审核
        request.setReportProcessStatus(ReportProcessStatus.TO_BE_REVIEWED.code);
        // 报告自身状态为书写完成
        request.setReportStatus(ReportStatus.WRITE_COMPLETED.code);
        // 调用中台签署报告服务
         listResult = docReportApi.saveDocReportByRegistrationAndExam(request);
        if (listResult.getStatus() != HttpStatus.OK.value()) {
            return listResult;
        }

        // 修改申请单状态
        modifyRequestFormStatus(request.getMsdServiceInstanceSoidList(), employeeSoid, request.getRequestSoid());
    } finally {
        // TODO 需要解锁报告
        //删除锁
        deleteLock(request, loginUser);
    }
        return listResult;
    }

    /**
     * 根据申请单标识，登记标识，检查号 报告回显
     *
     * @param request
     * @return
     */
    @Override
    public ListResult<ReportResult> getDocReportByTypes(DocReportInitializationRequest request, HttpServletRequest httpServletRequest) {
        ListResult result = new ListResult();
        Map<String, String> initializationMap = new HashMap<>();
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        Long employeeSoid = null;
        UserDto loginUser = userDtoresult.getData();
        if (ObjectUtils.isEmpty(loginUser)) {
            buildListWarn(result, "获取不到用户信息");
            return result;
        }
        employeeSoid = loginUser.getEmployeeSoid();

        request.setEmployeeSoid(employeeSoid);
        if (!ObjectUtils.isEmpty(employeeSoid)) {
            //根据员工的soid查找组织的soid
            ListResult<List<BaseOrgInfoVo>> hospitalByEmployeeSoid = iOrgInfoApi.findHospitalByEmployeeSoid(employeeSoid);
            if (!ObjectUtils.isEmpty(hospitalByEmployeeSoid) && !org.springframework.util.CollectionUtils.isEmpty(hospitalByEmployeeSoid.getData())) {
                List<BaseOrgInfoVo> data = hospitalByEmployeeSoid.getData();
                List<Long> orgInfoSoids = new ArrayList<>();
                data.stream().filter(baseOrgInfoVo -> !ObjectUtils.isEmpty(baseOrgInfoVo) && !ObjectUtils.isEmpty(baseOrgInfoVo.getOrgInfoSoid())).forEach(baseOrgInfoVo -> {
                    Long orgInfoSoid = baseOrgInfoVo.getOrgInfoSoid();
                    orgInfoSoids.add(orgInfoSoid);
                });
                Long orgInfoSoid = orgInfoSoids.get(0);

                //找到报告类型
                ListResult<ParameterDto> parameterByOrgInfoSoid = iParameterApi.findParameterByOrgInfoSoid(ReportType.REPORT_PARAMETERS_SOID.code, orgInfoSoid,
                        ReportType.WRITE_REPORT_RESOURCE_INFO_SOID.code);
                Long parameterValueSoid = null;
                if (ObjectUtils.isNotEmpty(parameterByOrgInfoSoid) && ObjectUtils.isNotEmpty(parameterByOrgInfoSoid.getData())) {
                    ParameterDto parameterDto = parameterByOrgInfoSoid.getData();
                    if (ObjectUtils.isNotEmpty(parameterDto) && !org.springframework.util.CollectionUtils.isEmpty(parameterDto.getParameterValueList())) {
                        List<MsdParameterValue> parameterValueList = parameterDto.getParameterValueList();
                        if (!org.springframework.util.CollectionUtils.isEmpty(parameterValueList)) {
                            for (MsdParameterValue msdParameterValue : parameterValueList) {
                                parameterValueSoid = msdParameterValue.getParameterValueSoid();
                                initializationMap.put("parameterValueSoid", parameterValueSoid.toString());
                            }
                            request.setDocReportInitializationMap(initializationMap);
                        }
                    }
                }
            }
            // 获取报告紧急标识
            String emergencySign = null;
            emergencySign = gainEmergencySign(request, emergencySign);
            initializationMap.put("emergencySign", emergencySign);
            request.setDocReportInitializationMap(initializationMap);
            return docReportApi.getDocReportByTypes(request);
        }
        return result;
    }

    /**
     * 根据申请单，登记单，检查单号初始化模板报告
     *
     * @param docReportInitializationRequest
     * @return
     */
    @Override
    public ListResult<ReportInitializationResult> initializeDocReportTypes(DocReportInitializationRequest docReportInitializationRequest, HttpServletRequest httpServletRequest) {
        //todo
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        String reportDoctor = null;
        UserDto loginUser = userDtoresult.getData();
        if (ObjectUtils.isEmpty(loginUser)) {
            ListResult result = new ListResult();
            buildListWarn(result, "获取不到用户信息");
            return result;
        }
        reportDoctor = loginUser.getNickname();

        Long reportType = docReportInitializationRequest.getReportType();
        ListResult result = new ListResult();

        if (ReportType.WRITE_REPORT_REQUEST.code.equals(reportType)) {
            // 按照申请单方式书写报告获取初始化报告信息
            ListResult<ReportInitializationResult> reportInitializationResultListResult = this.initializeDocReport(docReportInitializationRequest, httpServletRequest);
            return reportInitializationResultListResult;
            // 按照登记单/检查单方式书写报告获取初始化报告信息
        } else if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType) || ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
            if (!testDate) {
                // mock数据初始化模板报告-
                return gainInitializedReportInfoMock(docReportInitializationRequest, reportDoctor, loginUser, reportType, result);
            } else {
                log.info("开始初始化模板报告,初始化条件: " + "申请单标识: " + docReportInitializationRequest.getRequestSoid());
                StopWatch stopWatch = StopWatch.createStarted();
                ReportInitializationResult reportInitializationResult = new ReportInitializationResult();
                Map<String, String> info = new HashMap<>();

                if (ObjectUtils.isEmpty(docReportInitializationRequest.getRequestSoid())) {
                    log.error("申请单标识不能为空");
                    buildBadRequestListWarn(result, "申请单标识不能为空");
                    return result;
                }
                try {
                    List<RequestPsersonsoidRequest> requestList = new ArrayList<>();
                    RequestPsersonsoidRequest requestPsersonsoidRequest = new RequestPsersonsoidRequest();
                    List<RequestAndPatientInfoVo> patientMedicalByReuestSoids = new ArrayList<>();
                    if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType)) {
                        // todo:获取上游申请单信息，需要requestPsersonsoidRequest.setOperation
                        requestPsersonsoidRequest.setRequestSoid(docReportInitializationRequest.getRequestSoid().toString());
                        requestPsersonsoidRequest.setPersonSoid(docReportInitializationRequest.getPersonSoid());
                        requestList.add(requestPsersonsoidRequest);
                        patientMedicalByReuestSoids = requestFormService.findPatientMedicalByRequestSoids(requestList);
                    } else if (ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
                        // todo:获取上游申请单信息，需要requestPsersonsoidRequest.setRegistionNo
                        requestPsersonsoidRequest.setRequestSoid(docReportInitializationRequest.getRequestSoid().toString());
                        requestPsersonsoidRequest.setPersonSoid(docReportInitializationRequest.getPersonSoid());
                        requestList.add(requestPsersonsoidRequest);
                        patientMedicalByReuestSoids = requestFormService.findPatientMedicalByRequestSoids(requestList);
                    }
                    if (ObjectUtils.isNotEmpty(patientMedicalByReuestSoids)) {
                        // 打包初始化报告返回信息(一般信息,检查信息)
                        packInitializedReportInfoMerge(loginUser, result, reportInitializationResult, info, patientMedicalByReuestSoids);
                    }
                } catch (Exception e) {
                    log.error("初始化模板报告发送异常", e);
                    buildListWarn(result, "初始化模板报告失败");
                } finally {
                    stopWatch.stop();
                    log.info("本次初始化模板报告耗时: " + stopWatch.getTime() + "ms");
                }
                return result;
            }
        } else {
            buildBadRequestListWarn(result, "报告类型不匹配");
            return result;
        }
    }

    @NotNull
    private ListResult<ReportInitializationResult> gainInitializedReportInfoMock(DocReportInitializationRequest docReportInitializationRequest, String reportDoctor, UserDto loginUser, Long reportType, ListResult result) {
        // 切换初始化报告mock数据
        ReportInitializationResult reportInitializationResult = new ReportInitializationResult();
        List<PatientInfoVo> listTmp = new ArrayList<>();
        Map<String, String> info = new HashMap<>();
        if (ObjectUtils.isEmpty(docReportInitializationRequest.getRequestSoid())) {
            log.error("申请单标识不能为空");
            buildBadRequestListWarn(result, "申请单标识不能为空");
            return result;
        }
        if (ObjectUtils.isEmpty(docReportInitializationRequest.getExaminationVisitSoid())) {
            log.error("检查标识不能为空");
            buildBadRequestListWarn(result, "检查标识不能为空");
            return result;
        }
        Long operatorSoid = null;
        String registrationNo = null;
        if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType)) {
            operatorSoid = Long.valueOf(docReportInitializationRequest.getExaminationVisitSoid());
            //读取filePatientinfoByExam中的数据
            if (filePatientinfoByExam.exists()) {
                listTmp = ReportUtil.gainMockPatientInfo(listTmp, filePatientinfoByExam);
            }

        } else if (ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
            registrationNo = docReportInitializationRequest.getRegistrationNo();
            //读取filePatientinfoByRegistion中的数据
            if (filePatientinfoByRegistion.exists()) {
                listTmp = ReportUtil.gainMockPatientInfo(listTmp, filePatientinfoByRegistion);
            }
        }

        if (CollectionUtils.isNotEmpty(listTmp)) {
            // 打包初始化报告所需信息(一般信息,检查信息)
            for (int i = 0; i < listTmp.size(); i++) {
                PatientInfoVo patientInfoVo = listTmp.get(i);
                // 按申请单方式书写所需的信息
                if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType)) {
                    if (Long.valueOf(patientInfoVo.getExaminationVisitSoid()) == operatorSoid.longValue()) {
                        // 书写报告师签名
                        ReportUtil.packInitializedReportInfoMock(reportDoctor, info, patientInfoVo);
                    }
                    // 按登记单/检查单方式书写所需的信息
                } else if (ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
                    if (Long.valueOf(patientInfoVo.getRegistrationNo()) == Long.valueOf(registrationNo)) {
                        // 书写报告师签名
                        ReportUtil.packInitializedReportInfoMock(reportDoctor, info, patientInfoVo);
                    }
                }
                //判断医生类别
                String radiateWriteCode = "TJDY02";
                String radiateAuditCode = "TJDY07";
                String usWriteCode = "TJDY010";
                if (radiateWriteCode.equals(loginUser.getCurrentRole())) {
                    info.put(ReportFragmentSlotInfo.WRITE_DOC.code.toString(), loginUser.getUsername());
                }
                if (radiateAuditCode.equals(loginUser.getCurrentRole())) {
                    info.put(ReportFragmentSlotInfo.AUDIT_DOC.code.toString(), loginUser.getUsername());
                }
                if (usWriteCode.equals(loginUser.getCurrentRole())) {
                    info.put(ReportFragmentSlotInfo.WRITE_DOC.code.toString(), loginUser.getUsername());
                }
            }
        }
        reportInitializationResult.setRequisitionInfo(info);
        buildListSuccess(result, reportInitializationResult);
        return result;
    }

    /**
     * 根据申请单号，登记单号，检查号暂存报告
     *
     * @param request
     * @return
     */
    @Override
    public ListResult<ReportResult> saveTemporarilyTypes(DocReportPreservationRequest request, HttpServletRequest httpServletRequest) throws NoSuchFieldException {
        ListResult result = new ListResult();
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto loginUser = userDtoresult.getData();
        Long employeeSoid = null;
        if (ObjectUtils.isEmpty(loginUser)) {
            buildListWarn(result, "获取不到用户信息");
            return result;
        }
        employeeSoid = loginUser.getEmployeeSoid();


        // 角色标识
        String customerSoid = null;
        // 患者信息标识(From our system)
        String apntPersonSoid = null;
        // 病人标识(From HIS)
//        String patientSoid = null;
        String patientId = null;
        // 病人姓名
        String personName = null;
        //报告类型
        Long reportType = request.getReportType();
        //检查标识
        Long operatorSoid = null;
        //登记号
        String registrationNo = null;

        List<RequestPsersonsoidRequest> requestList = new ArrayList<>();
        RequestPsersonsoidRequest requestPsersonsoidRequest = new RequestPsersonsoidRequest();
        requestPsersonsoidRequest.setRequestSoid(request.getRequestSoid().toString());
        requestPsersonsoidRequest.setPersonSoid(request.getPersonSoid());
        requestList.add(requestPsersonsoidRequest);

        if (ReportType.WRITE_REPORT_REQUEST.code.equals(reportType)) {
            // 按申请单方式书写报告暂存
            result = this.saveTemporarily(request, httpServletRequest);
        } else if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType) || ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
            // 按登记号/检查号方式书写报告暂存
            Map<String, String> patientInfoMap = new HashMap<>();
            if (!testDate) {
                // mock数据获取申请单信息
                gainRoleAndPatientInfoMergeMock(request, employeeSoid, customerSoid, apntPersonSoid, patientId, reportType, operatorSoid, registrationNo, patientInfoMap);
            } else {
                // 获取上游申请单信息
                gainRoleAndPatientInfo(request, null, customerSoid, patientId, personName, requestList, requestPsersonsoidRequest, patientInfoMap);
            }

            // 报告自身状态为草稿
            request.setReportStatus(ReportStatus.DRAFT.code);
            // 报告流转状态为待书写
            request.setReportProcessStatus(ReportProcessStatus.TO_BE_WRITTEN.code);
            ListResult<ReportResult> reportResultListResult = docReportApi.saveTemporarilyTypes(request);

            return reportResultListResult;
        }
        return result;
    }


    @Override
    public ListResult<String> getReportPdfUrl(ReportSearchRequest request) {
        return docReportApi.getReportPdfUrl(request);

    }

    @Override
    public void getReportPdf(ReportSearchRequest request, HttpServletResponse httpServletResponse) {
        InputStream inputStream = null;
        OutputStream outputStream = null;

        Response reportPdf = docReportApi.getReportPdf(request);
        Response.Body body = reportPdf.body();
        try {
            inputStream = body.asInputStream();
            outputStream = httpServletResponse.getOutputStream();
            httpServletResponse.setContentType("application/pdf;charset=UTF-8");
            httpServletResponse.addHeader("Content-Disposition", "inline;filename=");
            byte[] c = new byte[1024];
            int length;
            while ((length = inputStream.read(c)) > 0) {
                outputStream.write(c, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("本次获取报告pdf发送异常", e);
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("pdf文件流关闭失败");
            }
        }

    }

    @Override
    public ActionResult publishReport(ReportPublishRequest reportPublishRequest, HttpServletRequest httpServletRequest) {
        ActionResult actionResult = new ActionResult();
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto loginUser = userDtoresult.getData();
        Long employeeSoid = null;
        if (ObjectUtils.isEmpty(loginUser)) {
            buildActionWarn(actionResult, "获取不到用户信息");
            return actionResult;
        }

        employeeSoid = loginUser.getEmployeeSoid();
        reportPublishRequest.setEmployeeSoid(employeeSoid);

        return docReportApi.publishReport(reportPublishRequest);
    }

    @Override
    public ActionResult recallReport(ReportRecallRequest reportRecallRequest, HttpServletRequest httpServletRequest) {
        ActionResult actionResult = new ActionResult();
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto loginUser = userDtoresult.getData();
        Long employeeSoid = null;
        if (ObjectUtils.isEmpty(loginUser)) {
            buildActionWarn(actionResult, "获取不到用户信息");
            return actionResult;
        }
        employeeSoid = loginUser.getEmployeeSoid();
        reportRecallRequest.setEmployeeSoid(employeeSoid);
        ListResult<ParameterDto> parameterByOrgInfoSoid = new ListResult();
        String dataValue = null;
        if (loginUser != null && loginUser.getHospitalSoid() != null) {
            // 读取主数据的召回报告时间配置
            parameterByOrgInfoSoid = mdmService.findParameterByOrgInfoSoid(
                    ReportType.RECALL_TIME_LIMIT.code, loginUser.getHospitalSoid(),
                    ReportType.WRITE_REPORT_RESOURCE_INFO_SOID.code);
            ParameterDto data = parameterByOrgInfoSoid.getData();
            if (ObjectUtils.isNotEmpty(data)) {
                List<MsdParameterValue> parameterValueList = data.getParameterValueList();
                if (CollectionUtils.isNotEmpty(parameterValueList)) {
                    dataValue = parameterValueList.get(0).getDataValue();
                    if (StringUtils.isNotEmpty(dataValue)) {
                        if (dataValue.equals("01")) {
                            // 报告发布后不可召回
                            reportRecallRequest.setRecallTimeLimit(0);
                        } else if (dataValue.equals("02")) {
                            // 报告发布30s内可召回
                            reportRecallRequest.setRecallTimeLimit(30);
                        } else if (dataValue.equals("03")) {
                            // 报告发布一分钟内可召回
                            reportRecallRequest.setRecallTimeLimit(60);
                        } else {
                            buildActionWarn(actionResult, "未配置报告召回时间控制");
                            return actionResult;
                        }
                    }
                }
            }
        }
        return docReportApi.recallReport(reportRecallRequest);
    }


    /**
     * 根据StReportSoid从docReportRequisitionRelation表中查询全部列表
     *
     * @param stReportSoid
     * @return
     */
    @Override
    public List<DocReportRequisitionRelationVo> selectByStReportSoid(Long stReportSoid) {
        return docReportApi.selectByStReportSoid(stReportSoid);
    }

    /**
     * 获取审核发布参数(01:审核发布一键操作,02:审核发布分两步操作)\
     *
     * @return
     */
    public ListResult getReviewPublishParam() {
        ListResult listResult = new ListResult();
        try {
            ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
            UserDto user = userDtoresult.getData();
            ListResult<ParameterDto> parameterByOrgInfoSoid = new ListResult();
            String dataValue = null;
            Map result = new HashMap();
            if (user != null && user.getHospitalSoid() != null) {
                parameterByOrgInfoSoid = mdmService.findParameterByOrgInfoSoid(
                        ReportType.REVIEW_PUBLISH_PARAM.code, user.getHospitalSoid(),
                        ReportType.WRITE_REPORT_RESOURCE_INFO_SOID.code);
                ParameterDto data = parameterByOrgInfoSoid.getData();
                if (ObjectUtils.isNotEmpty(data)) {
                    List<MsdParameterValue> parameterValueList = data.getParameterValueList();
                    if (CollectionUtils.isNotEmpty(parameterValueList)) {
                        dataValue = parameterValueList.get(0).getDataValue();
                    }
                }
            }
            result.put("dataValue", dataValue);
            buildListSuccess(listResult, result);
        } catch (Exception e) {
            log.error("获取审核发布参数失败", e);
            buildListWarn(listResult, "获取审核发布参数失败");
        }
        return listResult;
    }

    /**
     * 获取报告召回时间控制配置(01:报告发布后不可召回,02:报告发布30s内可召回,03:报告发布1分钟内可召回)
     *
     * @return
     */
    public ListResult getRecallLimit() {
        ListResult listResult = new ListResult();
        try {
            ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
            UserDto user = userDtoresult.getData();
            ListResult<ParameterDto> parameterByOrgInfoSoid = new ListResult();
            String dataValue = null;
            Map result = new HashMap();
            if (user != null && user.getHospitalSoid() != null) {
                parameterByOrgInfoSoid = mdmService.findParameterByOrgInfoSoid(
                        ReportType.RECALL_TIME_LIMIT.code, user.getHospitalSoid(),
                        ReportType.WRITE_REPORT_RESOURCE_INFO_SOID.code);
                ParameterDto data = parameterByOrgInfoSoid.getData();
                if (ObjectUtils.isNotEmpty(data)) {
                    List<MsdParameterValue> parameterValueList = data.getParameterValueList();
                    if (CollectionUtils.isNotEmpty(parameterValueList)) {
                        dataValue = parameterValueList.get(0).getDataValue();
                    }
                }
            }
            result.put("dataValue", dataValue);
            buildListSuccess(listResult, result);
        } catch (Exception e) {
            log.error("获取报告召回时间控制配置失败", e);
            buildListWarn(listResult, "获取报告召回时间控制配置失败");
        }
        return listResult;
    }

    /**
     * 打包初始化模板报告信息(按申请单方式书写的报告)
     *
     * @param user
     * @param result
     * @param reportInitializationResult
     * @param info
     * @param patientMedicalByRequestSoid
     */
    private void packInitializedReportInfo(UserDto user,
                                           ListResult result,
                                           ReportInitializationResult reportInitializationResult,
                                           Map<String, String> info,
                                           RequestAndPatientInfoVo patientMedicalByRequestSoid) {

        PatientPageInfoVo patientPageInfoVo = patientMedicalByRequestSoid.getPatientPageInfoVo();
        ReqeustServiceInstanceVo reqeustServiceInstanceVo = patientMedicalByRequestSoid.getReqeustServiceInstanceVo();

        packCommonInitializedReport(user, info, patientPageInfoVo, reqeustServiceInstanceVo);
        reportInitializationResult.setRequisitionInfo(info);
        buildListSuccess(result, reportInitializationResult);
    }

    /**
     * 打包初始化模板报告信息(按合单方式书写的报告)
     *
     * @param user
     * @param result
     * @param reportInitializationResult
     * @param info
     * @param patientMedicalByReuestSoids
     */
    private void packInitializedReportInfoMerge(UserDto user,
                                                ListResult result,
                                                ReportInitializationResult reportInitializationResult,
                                                Map<String, String> info,
                                                List<RequestAndPatientInfoVo> patientMedicalByReuestSoids) {

        for (RequestAndPatientInfoVo patientMedicalByRequestSoid : patientMedicalByReuestSoids) {
            PatientPageInfoVo patientPageInfoVo = patientMedicalByRequestSoid.getPatientPageInfoVo();
            ReqeustServiceInstanceVo reqeustServiceInstanceVo = patientMedicalByRequestSoid.getReqeustServiceInstanceVo();

            packCommonInitializedReport(user, info, patientPageInfoVo, reqeustServiceInstanceVo);
            //判断医生类别
            String radiateWriteCode = "TJDY02";
            String radiateAuditCode = "TJDY07";
            String usWriteCode = "TJDY010";
            if (radiateWriteCode.equals(user.getCurrentRole())) {
                info.put(ReportFragmentSlotInfo.WRITE_DOC.code.toString(), user.getNickname());
            }
            if (radiateAuditCode.equals(user.getCurrentRole())) {
                info.put(ReportFragmentSlotInfo.AUDIT_DOC.code.toString(), user.getNickname());
            }
            if (usWriteCode.equals(user.getCurrentRole())) {
                info.put(ReportFragmentSlotInfo.WRITE_DOC.code.toString(), user.getNickname());
            }
            reportInitializationResult.setRequisitionInfo(info);
            buildListSuccess(result, reportInitializationResult);
        }
    }

    /**
     * 拼装初始化模板报告信息
     *
     * @param user
     * @param info
     * @param patientPageInfoVo
     * @param reqeustServiceInstanceVo
     */
    private void packCommonInitializedReport(UserDto user, Map<String, String> info, PatientPageInfoVo patientPageInfoVo, ReqeustServiceInstanceVo reqeustServiceInstanceVo) {
        if (ObjectUtils.isNotEmpty(patientPageInfoVo)) {
            // 包装上游申请单信息到返回结果集中
            // 患者姓名
            info.put(ReportFragmentSlotInfo.PATIENT_NAME.code.toString(), patientPageInfoVo.getPersonName());
            // 性别
            info.put(ReportFragmentSlotInfo.GENDER.code.toString(), patientPageInfoVo.getGenderName());
            // 年龄
            info.put(ReportFragmentSlotInfo.AGE.code.toString(), patientPageInfoVo.getAge());
            // 门诊号
            info.put(ReportFragmentSlotInfo.OUT_PATIENT_NO.code.toString(), patientPageInfoVo.getOutpatientNo());
        }

        if (ObjectUtils.isNotEmpty(reqeustServiceInstanceVo)) {
            // 就诊场景代码
            String visitScenceCode = reqeustServiceInstanceVo.getVisitScenceCode();
            String visitScenceName = null;
            if (StringUtils.isNotEmpty(visitScenceCode)) {
                visitScenceName = detailCodingSystemService.getDataSetName(Long.valueOf(visitScenceCode));
            }
            // 检查技术
            String checkTechnical = reqeustServiceInstanceVo.getMedicalDeviceExampleDesc();
            // 检查方法
            String checkMethod = reqeustServiceInstanceVo.getMethodNames();
            // 登记号,检查号需要前端自己去列表中获取

            // 包装上游申请单信息到返回结果集中
            // 申请科室
            info.put(ReportFragmentSlotInfo.DEPARTMENT.code.toString(), reqeustServiceInstanceVo.getRequestDept());
            // 病人号
            info.put(ReportFragmentSlotInfo.PATIENT_NO.code.toString(), reqeustServiceInstanceVo.getPatientId());
            // 申请医生
            info.put(ReportFragmentSlotInfo.DOCTOR.code.toString(), reqeustServiceInstanceVo.getRequestDoctor());
            // 床号
            info.put(ReportFragmentSlotInfo.BED_NUMBER.code.toString(), reqeustServiceInstanceVo.getBedNo());
            // 住院号
            info.put(ReportFragmentSlotInfo.HOSPITALIZED_NUMBER.code.toString(), reqeustServiceInstanceVo.getPatientVisitSoid());
            // 检查部位
            info.put(ReportFragmentSlotInfo.CHECK_POSITION.code.toString(), reqeustServiceInstanceVo.getPartNames());
            // 检查目的
            info.put(ReportFragmentSlotInfo.CHECK_PURPOSE.code.toString(), reqeustServiceInstanceVo.getClinicalPurpose());
            // 就诊场景代码
            info.put(ReportFragmentSlotInfo.VISITING_SCENE.code.toString(), visitScenceName);
            // 检查方法
            info.put(ReportFragmentSlotInfo.CHECK_METHOD.code.toString(), checkMethod);
            // 检查技术
            info.put(ReportFragmentSlotInfo.CHECK_TECHNICAL.code.toString(), checkTechnical);
            // 加急标识
            info.put("emergencySign", reqeustServiceInstanceVo.getEmergencySign());
            info.put(ReportFragmentSlotInfo.WRITE_DOC.code.toString(), user.getNickname());
        }
    }

    private String gainRoleAndPatientInfo(DocReportPreservationRequest request,
                                          String submitDeptSoid,
                                          String customerSoid,
                                          String patientId,
                                          String personName,
                                          List<RequestPsersonsoidRequest> requestList,
                                          RequestPsersonsoidRequest requestPsersonsoidRequest,
                                          Map<String, String> patientInfoMap) throws NoSuchFieldException {
        String apntPersonSoid;
        log.info("开始获取上游申请单信息");
        StopWatch stopWatch = StopWatch.createStarted();
        // FIXME jian.li 调用过来的时候已经塞值了,这里重复塞值了
//        requestPsersonsoidRequest.setRequestSoid(request.getRequestSoid().toString());
//        requestPsersonsoidRequest.setPersonSoid(request.getPersonSoid());
//        requestList.add(requestPsersonsoidRequest);
        List<RequestAndPatientInfoVo> patientMedicalByRequestSoids = requestFormService.findPatientMedicalByRequestSoids(requestList);
        if (CollectionUtils.isNotEmpty(patientMedicalByRequestSoids)) {
            RequestAndPatientInfoVo patientMedicalByRequestSoid = patientMedicalByRequestSoids.get(0);
            if (ObjectUtils.isNotEmpty(patientMedicalByRequestSoid)) {
                ReqeustServiceInstanceVo reqeustServiceInstanceVo = patientMedicalByRequestSoid.getReqeustServiceInstanceVo();
                if (ObjectUtils.isNotEmpty(reqeustServiceInstanceVo)) {
                    //病人号
                    patientId = reqeustServiceInstanceVo.getPatientId();
                }
                PatientPageInfoVo patientPageInfoVo = patientMedicalByRequestSoid.getPatientPageInfoVo();
                if (ObjectUtils.isNotEmpty(patientPageInfoVo)) {
                    //预约角色标识
                    customerSoid = patientPageInfoVo.getCustomerSoid();
                    //患者姓名
                    personName = patientPageInfoVo.getPersonName();
                }
            }
        }
        // 患者信息标识(From our system)
        apntPersonSoid = request.getPersonSoid();
        patientInfoMap.put("customerSoid", customerSoid);
        patientInfoMap.put("apntPersonSoid", apntPersonSoid);
        patientInfoMap.put("patientSoid", patientId);
        patientInfoMap.put("submitDeptSoid", submitDeptSoid);
        request.setPatientInfoMap(patientInfoMap);

        stopWatch.stop();
        log.info("本次获取上游申请单信息耗时: " + stopWatch.getTime() + "ms");
        return personName;
    }

    private void gainRoleAndPatientInfoMock(DocReportPreservationRequest request,
                                            String submitDeptSoid,
                                            String customerSoid,
                                            String apntPersonSoid,
                                            String patientId,
                                            Map<String, String> patientInfoMap) {
        List<PatientInfoVo> listTmp = new ArrayList<>();
        if (filePatientinfo.exists()) {
            listTmp = ReportUtil.gainMockPatientInfo(listTmp, filePatientinfo);
        }

        if (CollectionUtils.isNotEmpty(listTmp)) {
            for (int i = 0; i < listTmp.size(); i++) {
                PatientInfoVo patientInfoVo = listTmp.get(i);
                if (patientInfoVo.getRequestNo().longValue() == request.getRequestSoid().longValue()) {
                    apntPersonSoid = patientInfoVo.getApntPersonSoid();
                }
            }
        }
        patientInfoMap.put("customerSoid", customerSoid);
        patientInfoMap.put("apntPersonSoid", apntPersonSoid);
        patientInfoMap.put("patientSoid", patientId);
        patientInfoMap.put("submitDeptSoid", submitDeptSoid);
        request.setPatientInfoMap(patientInfoMap);
    }

    private void gainRoleAndPatientInfoMergeMock(DocReportPreservationRequest request,
                                                 Long employeeSoid,
                                                 String customerSoid,
                                                 String apntPersonSoid,
                                                 String patientId,
                                                 Long reportType,
                                                 Long operatorSoid,
                                                 String registrationNo,
                                                 Map<String, String> patientInfoMap) {
        // 切换mock数据,获取角色标识,病人标识(from his),患者信息标识
        List<PatientInfoVo> listTmp = new ArrayList<>();
        if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType)) {
            operatorSoid = request.getExaminationVisitSoid();
            if (filePatientinfoByExam.exists()) {
                listTmp = ReportUtil.gainMockPatientInfo(listTmp, filePatientinfoByExam);
            }
        } else if (ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
            registrationNo = request.getRegistrationNo();
            //读取filePatientinfoByRegistion中的数据
            if (filePatientinfoByRegistion.exists()) {
                listTmp = ReportUtil.gainMockPatientInfo(listTmp, filePatientinfoByRegistion);
            }
        }

        if (CollectionUtils.isNotEmpty(listTmp)) {
            for (int i = 0; i < listTmp.size(); i++) {
                PatientInfoVo patientInfoVo = listTmp.get(i);
                if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(reportType)) {
                    if (Long.valueOf(patientInfoVo.getExaminationVisitSoid()) == operatorSoid.longValue()) {
                        customerSoid = patientInfoVo.getCustomerSoid();
                        patientId = patientInfoVo.getPatientNo();
                        apntPersonSoid = patientInfoVo.getApntPersonSoid();
                    }
                } else if (ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(reportType)) {
                    if (Long.valueOf(patientInfoVo.getRegistrationNo()) == Long.valueOf(registrationNo)) {
                        customerSoid = patientInfoVo.getCustomerSoid();
                        patientId = patientInfoVo.getPatientNo();
                        apntPersonSoid = patientInfoVo.getApntPersonSoid();
                    }
                }
            }
        }

        patientInfoMap.put("customerSoid", customerSoid);
        patientInfoMap.put("apntPersonSoid", apntPersonSoid);
        patientInfoMap.put("patientSoid", patientId);
        request.setPatientInfoMap(patientInfoMap);
        request.setEmployeeSoid(employeeSoid);
    }

    private String gainEmergencySign(DocReportInitializationRequest request, String emergencySign) {
        RespBody<QueryPatientMedicalReportVo> queryPatientMedicalReportVoRespBody = requestFormApi.queryRequestInfoByRequestSoidForResport(new BigDecimal(request.getRequestSoid()));
        if (ObjectUtils.isNotEmpty(queryPatientMedicalReportVoRespBody)) {
            QueryPatientMedicalReportVo queryPatientMedicalReportVo = queryPatientMedicalReportVoRespBody.getData();
            if (ObjectUtils.isNotEmpty(queryPatientMedicalReportVo)) {
                DataCenterPatientMedicalInfoVo dataCenterPatientMedicalInfoVo = queryPatientMedicalReportVo.getDataCenterPatientMedicalInfoVo();
                if (ObjectUtils.isNotEmpty(dataCenterPatientMedicalInfoVo)) {
                    emergencySign = dataCenterPatientMedicalInfoVo.getEmergency();
                }
            }
        }
        return emergencySign;
    }

    // 获取报告流水号
    private String gainReportVisitSoid(UserDto data) {
        String reportVisitSoid = null;
        Long orgInfoSoid = data.getHospitalSoid();
        ListResult<String> serialNumberBySoid = iCodingRuleInfoApi.getSerialNumberBySoid(CODING_RULE_INFO_SOID, orgInfoSoid, RESOURCE_INFO_SOID, null);
        reportVisitSoid = serialNumberBySoid.getData();
        return reportVisitSoid;
    }

    // 按申请单方式书写报告修改上游申请单状态
    private void modifyRequestFormStatus(List<String> msdServiceInstanceSoidList, Long employeeSoid, Long requestSoid) {
        for (String msdServiceInstanceSoid : msdServiceInstanceSoidList) {
            // 修改申请单状态
            ApntRequestLifeCycleVo apntRequest = new ApntRequestLifeCycleVo();
            apntRequest.setRequestSoid(BigDecimal.valueOf(requestSoid));
            apntRequest.setMsdServiceInstanceSoid(new BigDecimal(msdServiceInstanceSoid));
            apntRequest.setUpdateUser(BigDecimal.valueOf(employeeSoid));
            apntRequest.setOperate(RequestOperateEnum.REPORT);
            apntRequest.setUpdateDate(new Date());
            requestFormApi.insertRequestLifeCycle(apntRequest);
        }
    }

    // 按登记号/检查号方式书写报告修改上游申请单状态
    private void modifyRequestFormStatus(Long employeeSoid, List<DocReportRequisitionRelationVo> docReportRequisitionRelationVos) {
        for (DocReportRequisitionRelationVo docReportRequisitionRelationVo : docReportRequisitionRelationVos) {
            Long requestSoid = docReportRequisitionRelationVo.getRequestSoid();
            //修改申请单状态
            ApntRequestLifeCycleVo apntRequest = new ApntRequestLifeCycleVo();
            apntRequest.setRequestSoid(new BigDecimal(requestSoid));
            apntRequest.setOperate(RequestOperateEnum.REPORT);
            apntRequest.setUpdateUser(BigDecimal.valueOf(employeeSoid));
            apntRequest.setMsdServiceInstanceSoid(BigDecimal.valueOf(docReportRequisitionRelationVo.getMsdServiceInstanceSoid()));
            apntRequest.setUpdateDate(new Date());
            requestFormApi.insertRequestLifeCycle(apntRequest);
        }
    }

    /**
     * 保存危急值并转发到代理(网关)
     *
     * @param request
     * @return
     */
    @Override
    public ListResult<Long> saveCriticValue(CriticalValueRequest request) {

        ListResult listResult = new ListResult();
        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto loginUser = userDtoresult.getData();
        Long employeeSoid = null;
        Long submitDeptSoid = null;

        try {
            if (ObjectUtils.isEmpty(loginUser)) {
                ListResult result = new ListResult();
                buildBadRequestListWarn(listResult, "获取不到用户信息");
                return listResult;
            } else {
                employeeSoid = loginUser.getEmployeeSoid();
                List<String> businessUnitSoids = loginUser.getBusinessUnitSoids();
                if (CollectionUtils.isNotEmpty(businessUnitSoids)) {
                    submitDeptSoid = Long.valueOf(businessUnitSoids.get(0));
                }
            }
            request.setEmployeeSoid(employeeSoid);
            request.setSubmitDeptSoid(submitDeptSoid);

            // 保存报告危急值
            ListResult<Long> saveCritivalValueResult = docReportApi.saveCritivalValue(request);
            if (HttpStatus.OK.value() == saveCritivalValueResult.getStatus()) {
                if (ObjectUtils.isNotEmpty(saveCritivalValueResult.getData())) {
                    // 转发危急值到代理(网关)
                    transferCriticalValue(saveCritivalValueResult.getData(), request);
                    return saveCritivalValueResult;
                } else {
                    buildListWarn(listResult, "转发危急值到代理(网关失败)");
                }
            } else {
                buildListWarn(listResult, "保存报告危急值失败");
            }
        } catch (Exception e) {
            log.error("保存危急值并转发到代理失败");
            buildListWarn(listResult, "保存危急值并转发到代理失败");
        }

        return listResult;
    }

    ListResult transferCriticalValue(Long docReportCritivalValueSoid, CriticalValueRequest request) {
        log.info("危急值开始转发");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = simpleDateFormat.format(new Date());
        ListResult listResult = new ListResult();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        Map<String, Object> map = new HashMap();
        Map<String, String> requestBody = new HashMap();
        requestBody.put("docReportCritivalValueSoid", docReportCritivalValueSoid.toString());
        requestBody.put("criticalContent", request.getCriticalValueDesc());
        requestBody.put("apntPersonSoid", String.valueOf(request.getApntPersonSoid()));
        requestBody.put("personName", request.getPersonName());
        requestBody.put("submitDeptSoid", String.valueOf(request.getSubmitDeptSoid()));
        requestBody.put("submitter", String.valueOf(request.getEmployeeSoid()));
        requestBody.put("submitDate", date);
        // 开单科室
        requestBody.put("requestDept", String.valueOf(request.getRequestDept()));
        // 病区
        requestBody.put("nursingWardSoid", String.valueOf(request.getNursingWardSoid()));
        String bodyJson = JSONObject.toJSONString(requestBody);
        map.put("requestBody", bodyJson);
        Map<String, String> requestHeader = new HashMap();
        requestHeader.put("authorCode", criticalValueForwardConfiguration.getAuthorCode());
        requestHeader.put("clientId", criticalValueForwardConfiguration.getClientId());
        requestHeader.put("msgId", criticalValueForwardConfiguration.getMsgId());
        requestHeader.put("msgPriority", criticalValueForwardConfiguration.getMsgPriority());
        requestHeader.put("msgType", criticalValueForwardConfiguration.getMsgType());
        requestHeader.put("msgVersion", criticalValueForwardConfiguration.getMsgVersion());
        requestHeader.put("receiverDomainId", criticalValueForwardConfiguration.getReceiverDomainId());
        requestHeader.put("requestTime", date);
        requestHeader.put("senderDomainId", criticalValueForwardConfiguration.getSenderDomainId());
        map.put("requestHeader", requestHeader);
        String json = JSONObject.toJSONString(map);
        HttpEntity<String> httpEntity = new HttpEntity(json, headers);
        String result = null;
        int retryTimes = 4;
        do {
            try {
                result = restTemplate.postForObject(criticalUrl, httpEntity, String.class);
                break;
            } catch (Exception e) {
                log.error("危急值转发失败", e);
                log.info("危急值转发重试: " + retryTimes);
                retryTimes--;
            }
        } while (retryTimes > 0);

        if (StringUtils.isNotEmpty(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            Object code = jsonObject.get("code");
            if (code != null) {
                String s = code.toString();
                if (!s.equals("0000")) {
                    log.error("危急值转发失败", result);
                    buildListWarn(listResult, "危急值转发失败");
                } else {
                    buildListSuccess(listResult);
                    // 修改危急值主表状态为已发送
                    docReportApi.sentCriticalValue(Long.valueOf(docReportCritivalValueSoid));
                }
            }
        } else {
            buildListWarn(listResult, "危急值转发失败");
        }
        log.info("危急值转发结果: " + result);
        return listResult;
    }

    @Override
    public ListResult<ReportResult> getDocReportByStReportSoid(Long stReportSoid) {
        return docReportApi.getDocReportByStReportSoid(stReportSoid);
    }

    /**
     * @return void
     * @Author WXL
     * @Description 删除锁
     * @Date 2021/8/10
     * @Param [request, loginUser]
     **/
    private void deleteLock(DocReportPreservationRequest request, UserDto loginUser) {
        DocReportServiceLock docReportServiceLock = new DocReportServiceLock();
        docReportServiceLock.setRequestSoid(request.getRequestSoid());
        docReportServiceLock.setRegistrationSheetSoid(request.getRegistrationFormSoid());
        docReportServiceLock.setExamCheckSoid(request.getOperatorSoid());
        docReportServiceLock.setPolicySoid(request.getReportType());
        docReportServiceLockService.delete(docReportServiceLock, loginUser);
    }
}
